package com.reconcile.phone.common.utils.ip;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.reconcile.phone.common.exception.ServiceException;
import com.reconcile.phone.common.utils.file.FileUtils;
import java.io.File;

import com.reconcile.phone.system.domain.vo.AddressIpVo;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;

/**
 * 根据ip地址定位工具类，离线方式
 * 参考地址：<a href="https://gitee.com/lionsoul/ip2region/tree/master/binding/java">集成 ip2region 实现离线IP地址定位库</a>
 *
 * @author lishuyan
 */
@Slf4j
public class RegionUtils {

    private static final Searcher SEARCHER;

    static {
        String fileName = "/ip2region.xdb";
        File existFile = FileUtils.file(FileUtil.getTmpDir() + FileUtil.FILE_SEPARATOR + fileName);
        if (!FileUtils.exist(existFile)) {
            ClassPathResource fileStream = new ClassPathResource(fileName);
            if (ObjectUtil.isEmpty(fileStream.getStream())) {
                throw new ServiceException("RegionUtils初始化失败，原因：IP地址库数据不存在！");
            }
            FileUtils.writeFromStream(fileStream.getStream(), existFile);
        }

        String dbPath = existFile.getPath();

        // 1、从 dbPath 加载整个 xdb 到内存。
        byte[] cBuff;
        try {
            cBuff = Searcher.loadContentFromFile(dbPath);
        } catch (Exception e) {
            throw new ServiceException("RegionUtils初始化失败，原因：从ip2region.xdb文件加载内容失败！" + e.getMessage());
        }
        // 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。
        try {
            SEARCHER = Searcher.newWithBuffer(cBuff);
        } catch (Exception e) {
            throw new ServiceException("RegionUtils初始化失败，原因：" + e.getMessage());
        }
    }

    /**
     * 根据IP地址离线获取城市
     */
    public static String getCityInfo(String ip) {
      try {
        ip = ip.trim();
        // 3、执行查询
        String region = SEARCHER.search(ip);
        return region.replace("0|", "").replace("|0", "");
      } catch (Exception e) {
        log.error("IP地址离线获取城市异常 {}", ip);
        return "未知";
      }
    }

  /**
   * 根据IP地址离线获取城市(省市)
   */
  public static String getProvinceCity(String ip) {
    try {
      ip = ip.trim();
      // 3、执行查询
      String region = SEARCHER.search(ip);
      // 分割结果，获取省市信息
      String[] regions = region.split("\\|");
      if (regions.length > 2) {
        return regions[2] + regions[3];
      }
      return region.replace("0|", "").replace("|0", "");
    } catch (Exception e) {
      log.error("IP地址离线获取城市异常 {}", ip);
      return "未知";
    }
  }

    /**
     * 根据IP地址在线获取城市(省市)
     */
    public static AddressIpVo getProvinceCityOnline(String ip) {
        if (NetUtil.isInnerIP(ip)) {
            return new AddressIpVo();
        }
        /**
         * IP地址查询
         */
        String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
        //{"ip":"218.5.167.252","pro":"福建省","proCode":"350000","city":"泉州市","cityCode":"350500","region":"","regionCode":"0","addr":"福建省泉州市 电信ADSL","regionNames":"","err":""}
        String resultStr = HttpUtil.get(IP_URL + "?ip=" + ip + "&json=true");
        AddressIpVo addressIpVo= JSONUtil.toBean(resultStr, AddressIpVo.class);
        return addressIpVo;
    }

}
